package com.guyu.plugin.satoken.exception;


import cn.dev33.satoken.exception.*;
import com.guyu.common.core.entity.BizResult;
import com.guyu.common.core.exception.code.ErrorCodeEnum;
import com.guyu.common.web.filter.RepeatedlyRequestWrapper;
import com.guyu.common.web.util.GyServletUtils;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hutool.core.io.IoUtil;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.io.BufferedReader;
import java.io.IOException;

/**
 * <p> Sa-Token异常捕捉 </p>
 */
@Slf4j
@Order(Ordered.HIGHEST_PRECEDENCE)
@RestControllerAdvice
public class SaTokenExceptionHandler {

    public String getBody(ServletRequest request) {
        // 打印请求参数
        String contentType = request.getContentType();
        if (!GyServletUtils.isJsonRequest(contentType)) {
            return "";
        }
        if (request instanceof RepeatedlyRequestWrapper) {
            BufferedReader reader = null;
            try {
                reader = request.getReader();
            } catch (IOException e) {
                return "";
            }
            return IoUtil.read(reader);
        }
        return "";
    }

    public String getParams(HttpServletRequest request) {
        return GyServletUtils.getParamsJson(request);
    }

    /**
     * Sa-Token认证异常
     */
    @ExceptionHandler(value = SaTokenException.class)
    public BizResult handlerSaTokenException(HttpServletRequest request, SaTokenException e) {
        log.error("[GUYU]Sa-Token认证异常,URL[{}],body[{}],param:[{}]", request.getRequestURI(), getBody(request), getParams(request), e);
        return BizResult.error(ErrorCodeEnum.UNAUTHORIZED, e.getMessage());
    }

    /**
     * 登录认证异常
     */
    @ExceptionHandler(value = NotLoginException.class)
    public BizResult handlerNotLoginException(HttpServletRequest request, NotLoginException e) {
        log.error("[GUYU]登录认证异常,URL[{}],body[{}],param:[{}]", request.getRequestURI(), getBody(request), getParams(request), e);
        String message = "";
        if (e.getType().equals(NotLoginException.NOT_TOKEN)) {
            message = "认证失败，无法访问系统资源";
        } else if (e.getType().equals(NotLoginException.INVALID_TOKEN)) {
            message = "无效的token";
        } else if (e.getType().equals(NotLoginException.TOKEN_TIMEOUT)) {
            message = "token 已过期";
        } else if (e.getType().equals(NotLoginException.BE_REPLACED)) {
            message = "token 已被顶下线";
        } else if (e.getType().equals(NotLoginException.KICK_OUT)) {
            message = "token 已被踢下线";
        } else if (e.getType().equals(NotLoginException.TOKEN_FREEZE)) {
            message = "token 已被冻结";
        } else if (e.getType().equals(NotLoginException.NO_PREFIX)) {
            message = "认证失败，无法访问系统资源";
        } else {
            message = "认证失败，无法访问系统资源";
        }
        return BizResult.error(ErrorCodeEnum.RELOGIN, message);
    }

    /**
     * 权限认证异常
     */
    @ExceptionHandler(value = NotPermissionException.class)
    public BizResult handlerNotPermissionException(HttpServletRequest request, NotPermissionException e) {
        log.error("[GUYU]权限认证异常,URL[{}],body[{}],param:[{}]", request.getRequestURI(), getBody(request), getParams(request), e);
        return BizResult.error(ErrorCodeEnum.NOT_PERMISSION, e.getMessage());
    }

    /**
     * 角色认证异常
     */
    @ExceptionHandler(value = NotRoleException.class)
    public BizResult handlerNotRoleException(HttpServletRequest request, NotRoleException e) {
        log.error("[GUYU]角色认证异常,URL[{}],body[{}],param:[{}]", request.getRequestURI(), getBody(request), getParams(request), e);
        return BizResult.error(ErrorCodeEnum.NOT_ROLE, e.getMessage());
    }

    /**
     * 账号的指定服务已被封禁
     */
    @ExceptionHandler(value = DisableServiceException.class)
    public BizResult handlerDisableServiceException(HttpServletRequest request, DisableServiceException e) {
        log.error("[GUYU]账号的指定服务已被封禁,URL[{}],body[{}],param:[{}]", request.getRequestURI(), getBody(request), getParams(request), e);
        return BizResult.error(ErrorCodeEnum.FORBIDDEN, e.getMessage());
    }
}